import axios, {
  type AxiosError,
  type AxiosRequestConfig,
  type AxiosResponse
} from 'axios'
import { useUserStore } from '@/store/user'
import buildURL from 'axios/lib/helpers/buildURL'
import settle from 'axios/lib/core/settle'
import cache from '@/utils/cache'
import { type RefreshTokenResult } from '@/apis/login'
import { type ApiRes } from '@/apis/utils/common'

type ParamsSerializer = AxiosRequestConfig['paramsSerializer']

function getFullURL(
  baseURL: string,
  url: string,
  params: Record<string, any>,
  paramsSerializer?: ParamsSerializer
) {
  if (url.startsWith('http')) {
    return buildURL(url, params, paramsSerializer)
  }
  baseURL = baseURL.endsWith('/') ? baseURL : `${baseURL}/`
  url = url.startsWith('/') ? url.slice(1) : url
  return buildURL(`${baseURL}${url}`, params, paramsSerializer)
}

axios.defaults.adapter = async (config: AxiosRequestConfig) => {
  const { data, params } = config
  return await new Promise((resolve, reject) => {
    uni.request({
      method: config.method?.toUpperCase(),
      url: getFullURL(
        config.baseURL ?? '',
        config.url ?? '',
        params,
        config.paramsSerializer
      ),
      header: config.headers,
      data,
      // dataType: config.dataType ?? '',
      responseType: config.responseType,
      // sslVerify: config.sslVerify ?? '',
      // success: (res: any) => {
      //   console.log('uni request success ↓↓')
      //   console.log(res)
      //   resolve(res)
      // },
      complete: function complete(response: any) {
        // console.log('uni request complete ↓↓')
        // console.log(response)
        // const res = {} as AxiosResponse<ApiRes>
        // res.data = response.data
        // res.status = response.statusCode
        // res.statusText = response.errMsg
        // res.headers = response.headers
        // res.config = response.config
        const res = {
          data: response.data,
          status: response.statusCode,
          statusText: response.errMsg,
          headers: response.header, // 注意此处 单复数
          config
        }
        settle(resolve, reject, res)
      },
      fail: (err: any) => {
        console.log('uni request error ↓↓')
        console.log(err)
        // reject(err)
      }
    })
  })
}

// 创建axios实例
const axiosInst = axios.create({
  // axios的默认请求地址前缀
  // Web 侧可以通过 vite.config.js 中的 proxy 配置，指定代理
  // 可使用条件编译,详见 https://uniapp.dcloud.io/tutorial/platform.html#preprocessor
  // #ifdef H5
  // baseURL: import.meta.env.VITE_APP_AXIOS_BASE_URL,
  // #endif
  // 小程序APP里需写完整路径，如 https://service-rbji0bev-1256505457.cd.apigw.tencentcs.com/release
  // #ifndef H5
  // baseURL: 'https://nn.trd.ink/'
  // #endif
  baseURL: import.meta.env.VITE_API_URL + "/driver-app",
  timeout: 60000, // 默认的请求超时时间，单位毫秒
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
    appid: import.meta.env.VITE_WXMA_APPID
  }
})

axiosInst.interceptors.request.use(
  (config: any) => {
    // 得到 token
    const useStore = useUserStore()
    if (useStore?.token) {
      config.headers.Authorization = useStore.token
    }
    // 不缓存get请求
    // if (method === 'get') {
    //   headers['Cache-Control'] = 'no-cache'
    // }
    // 追加时间戳，防止GET请求缓存
    if (config.method?.toUpperCase() === 'GET') {
      config.params = { ...config.params, t: new Date().getTime() }
    }
    // config.headers.appid = import.meta.env.WXMA_APPID
    // config.headers.appid = 'wxd79fcf64e637172a'
    // delete请求参数放入body中
    // if (config.method === 'delete') {
    //   headers['Content-type'] = 'application/json;'
    //   Object.assign(config, {
    //     data: params,
    //     params: {}
    //   })
    // }
    return config
  },
  async (error) => {
    return await Promise.reject(error)
  }
)

const openLoginPage = () => {
  uni.navigateTo({
    url: '/pages/login/index'
  })
}
const showError = (msg: string) => {
  uni.showToast({ title: msg, icon: 'none' })
}
const handleAuthorized = async (navToLogin: boolean = true) => {
  // ElMessageBox.confirm('登录超时，请重新登录', '提示', {
  //   showCancelButton: false,
  //   closeOnClickModal: false,
  //   showClose: false,
  //   confirmButtonText: '重新登录',
  //   type: 'warning'
  // }).then(async () => {
  const userStore = useUserStore()
  userStore?.setToken('')
  userStore?.setRefreshToken('')
  // location.reload()
  // if (navToLogin) {
  //   openLoginPage()
  // }
  return await Promise.reject(new Error('登录超时，请重新登录'))
  // })
}

// 是否刷新
let isRefreshToken = false
let requests: any[] = [] // 重试队列数组，把需要刷新令牌的请求都放入这个数组中，每一项将是一个待执行的函数形式
// 令牌过期，刷新令牌请求
const getRefreshToken = <T>(refreshToken: string): Promise<T> => {
  return axiosInst.post('/app/auth/token?refreshToken=' + refreshToken)
}

// 响应拦截器
axiosInst.interceptors.response.use(
  async (response: AxiosResponse<ApiRes>) => {
    console.log('axios response ↓↓', response)
    const userStore = useUserStore()
    // 状态码不为200时
    if (response.status !== 200) {
      return await Promise.reject(new Error(response.statusText || 'Error'))
    }
    const res = response.data
    if (Object.prototype.toString.call(res) === '[object Blob]') {
      return response
    }
    // 响应成功
    if (res.code === 0) {
      return res.data
    }
    // refreshToken失效，跳转到登录页
    if (res.code === 400) {
      return await handleAuthorized()
    }
    // 没有权限，如：未登录、token过期
    if (res.code === 401) {
      // 后台要求刷新令牌
      const config = response.config
      if (
        config.headers?.ignore_refresh === true &&
        config.headers?.Authorization === null
      ) {
        return await handleAuthorized(false)
      }
      if (isRefreshToken) {
        // 如果正在刷新令牌状态为true  多个请求的情况
        return await new Promise((resolve) => {
          requests.push(() => {
            config.headers!.Authorization = userStore.token
            resolve(axiosInst(config))
          })
        })
      }
      // 如果正在刷新令牌状态为false
      // 获取刷新令牌请求
      const refreshToken = cache.getRefreshToken()
      if (!refreshToken) {
        return await handleAuthorized()
      }
      // 设置正在刷新令牌状态为true，进入更新令牌阶段
      isRefreshToken = true
      try {
        const data = await getRefreshToken<RefreshTokenResult>(refreshToken)
        // 刷新令牌成功，设置store及微信缓存中的账号信息
        userStore.setToken(data.access_token)
        config.headers!.Authorization = data.access_token
        // 已经刷新了令牌，重新发起重试队列数组中的请求
        requests.forEach((cb: any) => {
          cb()
        })
        // 完成后清空这个数组
        requests = []
        return await axiosInst(config)
      } catch (e) {
        // 刷新失败
        requests.forEach((cb: any) => {
          cb()
        })
        return await handleAuthorized()
      } finally {
        requests = []
        isRefreshToken = false
      }
    }
    // 错误提示
    showError(res.msg)
    return await Promise.reject(new Error(res.msg)) // 返回响应信息
  },
  async (error: AxiosError) => {
    return await Promise.reject(error) // 返回响应错误信息
  }
)

export default axiosInst
